package cloud.take.off.mybatis.search;

import cloud.take.off.mybatis.base.BaseEntity;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: gangan
 * @create: 2020-02-25 13:35
 */
public class SearchParamEntiy {
    private String paramMap;
    private Map<String, SearchParamObj> map;
    private static Map<Class, Map<String, String>> tableColumnMap = new HashMap();
    private static Map<Class, Map<String, Class>> tableFieldMap = new HashMap();

    private boolean loadMapInfo() {
        if (this.paramMap == null) {
            return false;
        } else {
            this.map = (Map) JSON.parseObject(this.paramMap, new TypeReference<Map<String, SearchParamObj>>() {
            }, new Feature[0]);
            return true;
        }
    }

    private static Map<String, String> getTableInfo(Class c) {
        return getMapInfo(c, "column");
    }

    private static Map<String, Class> getClassFieldInfo(Class c) {
        return getMapInfo(c, "field");
    }

    private static Map getMapInfo(Class c, String type) {
        Map map = null;
        byte var4 = -1;
        switch(type.hashCode()) {
            case -1354837162:
                if ("column".equals(type)) {
                    var4 = 0;
                }
                break;
            case 97427706:
                if ("field".equals(type)) {
                    var4 = 1;
                }
                break;
            default:
                break;
        }

        switch(var4) {
            case 0:
                map = tableColumnMap;
                break;
            case 1:
                map = tableFieldMap;
                break;
            default:
                return null;
        }

        if (map.containsKey(c)) {
            return (Map)map.get(c);
        } else {
            Class var3 = Class.class;
            synchronized(Class.class) {
                if (map.containsKey(c)) {
                    return (Map)map.get(c);
                } else {
                    byte var5 = -1;
                    switch(type.hashCode()) {
                        case -1354837162:
                            if ("column".equals(type)) {
                                var5 = 0;
                            }
                            break;
                        case 97427706:
                            if ("field".equals(type)) {
                                var5 = 1;
                            }
                            break;
                        default:
                            break;
                    }

                    switch(var5) {
                        case 0:
                            return getColumnInfo(c);
                        case 1:
                            return getFieldInfo(c);
                        default:
                            return null;
                    }
                }
            }
        }
    }

    private static Map<String, Class> getFieldInfo(Class c) {
        Map<String, Class> fieldInfo = new HashMap();
        Field[] fields = c.getDeclaredFields();
        Field[] var3 = fields;
        int var4 = fields.length;

        int var5;
        Field field;
        for(var5 = 0; var5 < var4; ++var5) {
            field = var3[var5];
            fieldInfo.put(field.getName(), field.getType());
        }

        if (BaseEntity.class.isAssignableFrom(c)) {
            fields = BaseEntity.class.getDeclaredFields();
            var3 = fields;
            var4 = fields.length;

            for(var5 = 0; var5 < var4; ++var5) {
                field = var3[var5];
                fieldInfo.put(field.getName(), field.getType());
            }
        }

        tableFieldMap.put(c, fieldInfo);
        return fieldInfo;
    }

    private static Map<String, String> getColumnInfo(Class c) {
        TableInfo tableInfo = SqlHelper.table(c);
        Map<String, String> columnInfo = new HashMap();
        Iterator var3 = tableInfo.getFieldList().iterator();

        while(var3.hasNext()) {
            TableFieldInfo attr = (TableFieldInfo)var3.next();
            columnInfo.put(attr.getProperty(), attr.getColumn());
        }

        columnInfo.put("id", "id");
        tableColumnMap.put(c, columnInfo);
        return columnInfo;
    }

    public QueryWrapper getQueryWrapper(QueryWrapper wrapper) {
        Object obj = wrapper.getEntity();
        JSONObject objJson = JSONObject.parseObject(JSONObject.toJSONString(obj));
        Map<String, SearchParamObj> searchMap = new HashMap();
        Map<String, String> columnInfo = getTableInfo(obj.getClass());
        if (this.loadMapInfo()) {
            Iterator var6 = this.map.entrySet().iterator();

            while(var6.hasNext()) {
                Map.Entry<String, SearchParamObj> entry = (Map.Entry)var6.next();
                String attrName = (String)entry.getKey();
                SearchParamObj param = (SearchParamObj)entry.getValue();
                if (objJson.containsKey(attrName)) {
                    Object value = objJson.get(attrName);
                    objJson.remove(attrName);
                    if (!"".equals(value)) {
                        param.setSingleParamValue(value);
                        searchMap.put(attrName, param);
                    }
                }
            }
        }

        Object searchObj = JSONObject.toJavaObject(objJson, obj.getClass());
        wrapper.setEntity(searchObj);
        Iterator var15 = searchMap.entrySet().iterator();

        while(true) {
            while(var15.hasNext()) {
                Map.Entry<String, SearchParamObj> entry = (Map.Entry)var15.next();
                String attrName = (String)entry.getKey();
                SearchParamObj param = (SearchParamObj)entry.getValue();
                if (param.getSingleLogic() != null) {
                    if (param.getSingleParamValue() != null) {
                        wrapper = param.getSingleLogic().addCondition(wrapper, (String)columnInfo.get(param.getParam()), param.getSingleParamValue());
                    }
                } else {
                    Iterator var11 = param.getMultiParam().iterator();

                    while(var11.hasNext()) {
                        SearchParamInfo one = (SearchParamInfo)var11.next();
                        if (one.getParam() != null) {
                            wrapper = one.getLogic().addCondition(wrapper, (String)columnInfo.get(one.getParam()), one.getParamValue());
                        }
                    }
                }
            }

            return wrapper;
        }
    }

    public SearchParamEntiy() {
    }

    public String getParamMap() {
        return this.paramMap;
    }

    public void setParamMap(String paramMap) {
        this.paramMap = paramMap;
    }

    public Map<String, SearchParamObj> getMap() {
        return this.map;
    }

    public void setMap(Map<String, SearchParamObj> map) {
        this.map = map;
    }

    public static QueryWrapper getQueryWrapper(QueryWrapper wrapper, List<SearchEntity> entityList) {
        return getQueryWrapper(wrapper, entityList, false);
    }

    public static QueryWrapper getQueryWrapper(QueryWrapper wrapper, List<SearchEntity> entityList, Boolean isRigid) {
        Object obj = wrapper.getEntity();
        Map<String, String> columnInfo = getTableInfo(obj.getClass());
        if (Optional.ofNullable(entityList).isPresent()) {
            Iterator var5 = entityList.iterator();

            while(true) {
                while(true) {
                    SearchEntity entity;
                    String field;
                    Object value;
                    do {
                        do {
                            if (!var5.hasNext()) {
                                return wrapper;
                            }

                            entity = (SearchEntity)var5.next();
                            field = entity.getField();
                            value = entity.getValue();
                        } while(isRigid && !columnInfo.containsKey(field));
                    } while(ObjectUtil.isEmpty(entity.getCondition()));

                    String col = field;
                    if (columnInfo.containsKey(field)) {
                        col = (String)columnInfo.get(field);
                    }

                    if (entity.getCondition() != Logic.in && entity.getCondition() != Logic.notIn) {
                        if (entity.getCondition() == Logic.like
                                && value instanceof String
                                && StrUtil.isBlank((String)value)){
                            continue;
                        }
                        wrapper = entity.getCondition().addCondition(wrapper, col, value);
                    } else {
                        List list = (List)value;
                        if (CollectionUtil.isNotEmpty(list)){
                            String[] values = new String[list.size()];
                            for (int i = 0; i<list.size(); i++){
                                values[i] = String.valueOf(list.get(i));
                            }
                            wrapper = entity.getCondition().addCondition(wrapper, col, values);
                        }
                    }
                }
            }
        } else {
            return wrapper;
        }
    }

}
